package com.htiiot.elasticsearch;

import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestActions;
import org.elasticsearch.rest.action.RestStatusToXContentListener;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestRequest.Method.PUT;

/**
 * elasticsearch 5.x
 *
 * @author 李延念
 * @create 2018-06-29 11:25
 **/
public class HTRestIndexAction5  extends BaseRestHandler {
    private final static Logger logger = LogManager.getLogger(HTRestIndexAction5.class);
    private static String ipToPrimeNumber;
    @Inject
    public HTRestIndexAction5(Settings settings, RestController controller) {
        super(settings);
        controller.registerHandler(POST, "/ht/{index}/{type}", this); // auto id creation
        controller.registerHandler(PUT, "/ht/{index}/{type}/{id}", this);
        controller.registerHandler(POST, "/ht/{index}/{type}/{id}", this);
        HTRestIndexAction5.CreateHandler createHandler = new HTRestIndexAction5.CreateHandler(settings);
        controller.registerHandler(PUT, "/ht/{index}/{type}/{id}/_create", createHandler);
        controller.registerHandler(POST, "/ht/{index}/{type}/{id}/_create", createHandler);
        List<String> networkAddress = getNetworkAddress();
        logger.info("get ip from localhost ,the ip is "+networkAddress);
        if(networkAddress != null && networkAddress.size() > 0){
            ipToPrimeNumber(networkAddress.get(0));
        }
    }

    public List<String> getNetworkAddress() {
        List<String> result = new ArrayList<String>();
        Enumeration<NetworkInterface> netInterfaces;
        try {
            netInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
                Enumeration<InetAddress> addresses=ni.getInetAddresses();
                while(addresses.hasMoreElements()){
                    ip = addresses.nextElement();
                    if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf(':') == -1) {
                        result.add(ip.getHostAddress());
                    }
                }
            }
            return result;
        } catch (Exception e) {
            return null;
        }
    }

    private void ipToPrimeNumber(String ip){
        String[] ipSplit = ip.split("\\.");
        if(ipSplit.length > 0 && ipSplit.length == 4){
            ipToPrimeNumber = (Integer.parseInt(ipSplit[0])*3+Integer.parseInt(ipSplit[1])*5+Integer.parseInt(ipSplit[2])*7+Integer.parseInt(ipSplit[3])*11)+"";
            logger.info("ipToPrimeNumber is [" + ipToPrimeNumber + "]");
        }
    }

    final class CreateHandler extends BaseRestHandler {
        protected CreateHandler(Settings settings) {
            super(settings);
        }

        @Override
        public RestChannelConsumer prepareRequest(RestRequest request, final NodeClient client) throws IOException {
            request.params().put("op_type", "create");
            return HTRestIndexAction5.this.prepareRequest(request, client);
        }
    }

    @Override
    public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
        String idPre = request.param("id");
        if(ipToPrimeNumber == null && idPre == null){
            logger.error("ipToPrimeNumber is null and idPre is null");
            return null;
        }
        String idGet = ipToPrimeNumber + System.currentTimeMillis();
        String id = idPre != null ? idPre : idGet + "";

        IndexRequest indexRequest = new IndexRequest(request.param("index"), request.param("type"), id);
        indexRequest.routing(request.param("routing"));
        indexRequest.parent(request.param("parent")); // order is important, set it after routing, so it will set the routing
        indexRequest.timestamp(request.param("timestamp"));
        if (request.hasParam("ttl")) {
            indexRequest.ttl(request.param("ttl"));
        }
        indexRequest.setPipeline(request.param("pipeline"));
        indexRequest.source(request.content());
        indexRequest.timeout(request.paramAsTime("timeout", IndexRequest.DEFAULT_TIMEOUT));
        indexRequest.setRefreshPolicy(request.param("refresh"));
        indexRequest.version(RestActions.parseVersion(request));
        indexRequest.versionType(VersionType.fromString(request.param("version_type"), indexRequest.versionType()));
        String sOpType = request.param("op_type");
        String waitForActiveShards = request.param("wait_for_active_shards");
        if (waitForActiveShards != null) {
            indexRequest.waitForActiveShards(ActiveShardCount.parseString(waitForActiveShards));
        }
        if (sOpType != null) {
            indexRequest.opType(IndexRequest.OpType.fromString(sOpType));
        }

        return channel ->
                client.index(indexRequest, new RestStatusToXContentListener<>(channel, r -> r.getLocation(indexRequest.routing())));
    }



}
